use serde::{Deserialize, Serialize};

/// Database type enumeration
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DatabaseType {
    PostgreSQL,
    MySQL,
    SQLite,
    MongoDB,
    Redis,
    Oracle,
    SqlServer,
    Cassandra,
    InfluxDB,
    Neo4j,
}

impl DatabaseType {
    /// Get the default port for this database type
    pub fn default_port(&self) -> u16 {
        match self {
            DatabaseType::PostgreSQL => 5432,
            DatabaseType::MySQL => 3306,
            DatabaseType::SQLite => 0, // File-based
            DatabaseType::MongoDB => 27017,
            DatabaseType::Redis => 6379,
            DatabaseType::Oracle => 1521,
            DatabaseType::SqlServer => 1433,
            DatabaseType::Cassandra => 9042,
            DatabaseType::InfluxDB => 8086,
            DatabaseType::Neo4j => 7687,
        }
    }
    
    /// Check if this database type supports SQL
    pub fn supports_sql(&self) -> bool {
        matches!(self, 
            DatabaseType::PostgreSQL | 
            DatabaseType::MySQL | 
            DatabaseType::SQLite | 
            DatabaseType::Oracle | 
            DatabaseType::SqlServer
        )
    }
    
    /// Get the display name for this database type
    pub fn display_name(&self) -> &'static str {
        match self {
            DatabaseType::PostgreSQL => "PostgreSQL",
            DatabaseType::MySQL => "MySQL",
            DatabaseType::SQLite => "SQLite",
            DatabaseType::MongoDB => "MongoDB",
            DatabaseType::Redis => "Redis",
            DatabaseType::Oracle => "Oracle",
            DatabaseType::SqlServer => "SQL Server",
            DatabaseType::Cassandra => "Cassandra",
            DatabaseType::InfluxDB => "InfluxDB",
            DatabaseType::Neo4j => "Neo4j",
        }
    }
}

/// Connection string builder
#[derive(Debug, Clone)]
pub struct ConnectionString {
    pub database_type: DatabaseType,
    pub host: String,
    pub port: u16,
    pub database: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub ssl: bool,
    pub additional_params: Vec<(String, String)>,
}

impl ConnectionString {
    /// Create a new connection string builder
    pub fn new(database_type: DatabaseType) -> Self {
        Self {
            database_type: database_type.clone(),
            host: "localhost".to_string(),
            port: database_type.default_port(),
            database: String::new(),
            username: None,
            password: None,
            ssl: false,
            additional_params: Vec::new(),
        }
    }
    
    /// Set the host
    pub fn host(mut self, host: impl Into<String>) -> Self {
        self.host = host.into();
        self
    }
    
    /// Set the port
    pub fn port(mut self, port: u16) -> Self {
        self.port = port;
        self
    }
    
    /// Set the database name
    pub fn database(mut self, database: impl Into<String>) -> Self {
        self.database = database.into();
        self
    }
    
    /// Set the username
    pub fn username(mut self, username: impl Into<String>) -> Self {
        self.username = Some(username.into());
        self
    }
    
    /// Set the password
    pub fn password(mut self, password: impl Into<String>) -> Self {
        self.password = Some(password.into());
        self
    }
    
    /// Enable SSL
    pub fn ssl(mut self, ssl: bool) -> Self {
        self.ssl = ssl;
        self
    }
    
    /// Add additional parameter
    pub fn param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
        self.additional_params.push((key.into(), value.into()));
        self
    }
    
    /// Build the connection string
    pub fn build(&self) -> String {
        match self.database_type {
            DatabaseType::PostgreSQL => {
                let mut url = format!("postgresql://");
                if let (Some(username), Some(password)) = (&self.username, &self.password) {
                    url.push_str(&format!("{}:{}@", username, password));
                }
                url.push_str(&format!("{}:{}/{}", self.host, self.port, self.database));
                
                if self.ssl {
                    url.push_str("?sslmode=require");
                }
                
                url
            }
            DatabaseType::MySQL => {
                let mut url = format!("mysql://");
                if let (Some(username), Some(password)) = (&self.username, &self.password) {
                    url.push_str(&format!("{}:{}@", username, password));
                }
                url.push_str(&format!("{}:{}/{}", self.host, self.port, self.database));
                url
            }
            DatabaseType::SQLite => {
                self.database.clone()
            }
            _ => {
                // TODO: Implement other database types
                format!("{}://{}:{}/{}", 
                    self.database_type.display_name().to_lowercase(),
                    self.host, 
                    self.port, 
                    self.database
                )
            }
        }
    }
}
